#include "../StdInc.h"

namespace GSTrader
{
	namespace Indicator
	{
		BOLL::BOLL()
		{
			m_strIndicatorName = "BOLL";

			m_M = 0;
			m_N = 0;
			m_nBarType = bdtClose;

			m_pStdUpper = new StdDev;
			m_pStdLower = new StdDev;
			m_pMa = new MA;

			m_pMid = m_pResult;
			m_pMid->m_strName = "MID";

			m_pUpper = new CIndicatorResult;
			m_pUpper->m_strName = "UPPER";
			m_vResult.push_back(m_pUpper);

			m_pLower = new CIndicatorResult;
			m_pLower->m_strName = "LOWER";
			m_vResult.push_back(m_pLower);
		}


		BOLL::~BOLL()
		{
			_delete(m_pStdUpper)
			_delete(m_pStdLower)
			_delete(m_pMa)
		}

		CIndicator* BOLL::CreateInstance()
		{
			return new BOLL;
		}

		void BOLL::SetParam(double* pdParam)
		{
			if (pdParam == NULL)
				return;

			m_M = (int)pdParam[0];
			m_N = (int)pdParam[1];
			m_nBarType = (int)pdParam[2];

			m_pMa->SetOneParam(m_M, m_nBarType);
			m_pStdUpper->SetParam(m_M, m_nBarType);
			m_pStdLower->SetParam(m_M, m_nBarType);

			RefreshData();
		}

		void BOLL::RefreshData()
		{
			if (m_pInput == NULL || m_pInput->m_nStartIndex < 0)
			{
				m_pMid->m_pDataSeries->m_nStartIndex = -1;
				m_pUpper->m_pDataSeries->m_nStartIndex = -1;
				m_pLower->m_pDataSeries->m_nStartIndex = -1;
				m_bCalc = true;
				return;
			}
				

			int nCount = m_pInput->GetCount();
			int nStartIndex = m_pInput->m_nStartIndex + m_M - 1;
			
			m_pMid->m_pDataSeries->SetSize(nCount, nStartIndex); 
			m_pUpper->m_pDataSeries->SetSize(nCount, nStartIndex);
			m_pLower->m_pDataSeries->SetSize(nCount, nStartIndex);

			m_bCalc = true;
		}

		double BOLL::Calculate(int nIndex)
		{
			if (m_pInput == NULL || m_pInput->m_nStartIndex < 0 || m_M < 1)
				return 0;

			int nCount = m_pInput->GetCount();
			if (nCount < m_pInput->m_nStartIndex + m_M + 1)
				return 0;

			m_pMa->Calculate(nIndex);
			m_pStdUpper->Calculate(nIndex);
			m_pStdLower->Calculate(nIndex);

			double dMid = m_pMa->GetResultValue(0, nIndex);
			double dStdUpper = m_pStdUpper->GetResultValue(0, nIndex);
			double dStdLower = m_pStdLower->GetResultValue(0, nIndex);

			m_pMid->SetValue(nIndex, dMid);
			m_pUpper->SetValue(nIndex, dMid + m_N * dStdUpper);
			m_pLower->SetValue(nIndex, dMid - m_N * dStdLower);

			return 1;
		}

		void BOLL::SetInputSeries(CSeries* pSeries)
		{
			m_pMa->SetInputSeries(pSeries);
			m_pStdUpper->SetInputSeries(pSeries);
			m_pStdLower->SetInputSeries(pSeries);

			CIndicator::SetInputSeries(pSeries);
		}
	}
}